package solved;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;

/*
ID:		liluyan1
LANG:	JAVA
TASK:	castle
*/
public class castle {
	public static void main(String[] args) throws IOException {
		BufferedReader f = new BufferedReader(new FileReader("castle.in"));
		PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(
				"castle.out")));
		new castle().solve(f, out);
		out.close();
		System.exit(0);
	}
	
	private final static int WEST 	= 1;
	private final static int NORTH 	= 2;
	
	private void solve(BufferedReader f, PrintWriter out) throws IOException {
		int[] a = read(f, 2);
		int M = a[0], N = a[1];
		int[][] matrix = new int[N][M];
		for (int i=0; i<N; i++) matrix[i] = read(f, M);
		
		int[][] color = new int[N][M];
		int[] count = new int[M*N];
		int next = 0;
		ArrayList<Pair> list = new ArrayList<Pair>();
		HashMap<Pair, Wall> map = new HashMap<Pair, Wall>();
		
		for (int i=0; i<N; i++) {
			for (int j=0; j<M; j++) {
				int c1 = (i > 0 && (matrix[i][j] & NORTH) == 0)? color[i-1][j] : -1;
				int c2 = (j > 0 && (matrix[i][j] & WEST) == 0)? color[i][j-1] : -1;

				if (c1<0 && c2<0) {
					color[i][j] = next;
					next++;
				}
				else if (c1>=0 && c2>=0) {
					color[i][j] = Math.min(c1, c2);
					list.add(new Pair(c1, c2));
				}
				else {
					color[i][j] = Math.max(c1, c2);
				}
				count[color[i][j]]++;
				
				// calculate wall
				if (i>0 && (matrix[i][j] & NORTH) > 0 && color[i][j]!=color[i-1][j]) {
					Pair id = new Pair(color[i][j], color[i-1][j]);
					Wall w = new Wall(i, j, 'N');
					if (map.containsKey(id)) {
						Wall w2 = map.get(id);
						if (w.lessThan(w2)) map.put(id, w);
					}
					else {
						map.put(id, w);
					}
				}
				
				if (j>0 && (matrix[i][j] & WEST) > 0 && color[i][j] != color[i][j-1]) {
					Pair id = new Pair(color[i][j], color[i][j-1]);
					Wall w = new Wall(i, j-1, 'E');
					if (map.containsKey(id)) {
						Wall w2 = map.get(id);
						if (w.lessThan(w2)) map.put(id, w);
					}
					else {
						map.put(id, w);
					}
				}
			}
		}
		
		// merge
		int total = next;
		int max = 1;
		ArrayList<MySet> sets = new ArrayList<MySet>();
		for (int i=0; i<total; i++) {
			MySet s = new MySet(count[i]);
			s.add(i);
			sets.add(s);
			max = Math.max(max, count[i]);
		}
		
		for (Pair p : list) {
			MySet s1 = findSet(p.x, sets);
			MySet s2 = findSet(p.y, sets);
			if (s1 == s2) continue;
			s1.addAll(s2);
			s1.addCount(s2.count);
			sets.remove(s2);
			max = Math.max(max, s1.count);
		}
		
		out.println(sets.size());
		out.println(max);
		
		Wall wMax = null;
		for (Pair p : map.keySet()) {
			MySet s1 = findSet(p.x, sets);
			MySet s2 = findSet(p.y, sets);
			if (s1 == s2) continue;
			int merge = s1.count + s2.count;
			if (merge > max) {
				max = merge;
				wMax = map.get(p);
			}
			else if (merge == max && map.get(p).lessThan(wMax)) {
				wMax = map.get(p);
			}
		}
		
		out.println(max);
		out.println(wMax.toString());
	}
	
	private MySet findSet(int color, ArrayList<MySet> sets) {
		for (MySet s : sets) {
			if (s.contains(color)) return s;
		}
		return null;
	}
	
	private class Wall {
		int x, y;
		char direction;
		public Wall(int x, int y, char direction) {
			this.x = x;
			this.y = y;
			this.direction = direction;
		}
		
		public boolean lessThan(Wall w) {
			if (y < w.y) return true;
			if (y > w.y) return false;
			if (x > w.x) return true;
			if (x < w.x) return false;
			return direction=='N' && w.direction=='E';
		}
		
		public String toString() {
			return (x+1) + " " + (y+1) + " " + direction;
		}
	}
	
	private class MySet<Integer> extends HashSet<Integer> {
		int count;
		
		public MySet(int count) {
			this.count = count;
		}
		
		public void addCount(int count) {
			this.count += count;
		}
	}
	
	private class Pair {
		int x, y;
		public Pair(int x, int y) {
			this.x = Math.min(x, y);
			this.y = Math.max(x, y);
		}
		
		public boolean equals(Object p) {
			Pair p2 = (Pair) p;
			return x == p2.x && y == p2.y;
		}
		
		public int hashCode() {
			return x*50 + y;
		}
	}
	
	public int read(BufferedReader f) throws IOException {
		return Integer.parseInt(f.readLine());
	}
	
	public int[] read(BufferedReader f, int N) throws IOException {
		String[] t = f.readLine().split(" ");
		int[] a = new int[N];
		for (int i=0; i<N; i++) {
			a[i] = Integer.parseInt(t[i]);
		}
		return a;
	}
}
